package com.xjrsoft.module.erpModel.caseErpStore.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.lang.TypeReference;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.xjrsoft.common.constant.GlobalConstant;
import com.xjrsoft.common.enums.YesOrNoEnum;
import com.xjrsoft.common.utils.RedisUtil;
import com.xjrsoft.module.erpModel.caseErpMaterial.entity.CaseErpMaterial;
import com.xjrsoft.module.erpModel.caseErpMaterial.service.ICaseErpMaterialService;
import com.xjrsoft.module.erpModel.caseErpPurchase.entity.CaseErpApplyDetail;
import com.xjrsoft.module.erpModel.caseErpStore.dto.AddCaseErpStoreReceiptDetailDto;
import com.xjrsoft.module.erpModel.caseErpStore.dto.AddCaseErpStoreReceiptDto;
import com.xjrsoft.module.erpModel.caseErpStore.dto.UpdateCaseErpStoreReceiptDetailDto;
import com.xjrsoft.module.erpModel.caseErpStore.dto.UpdateCaseErpStoreReceiptDto;
import com.xjrsoft.module.erpModel.caseErpStore.entity.CaseErpStoreReceipt;
import com.xjrsoft.module.erpModel.caseErpStore.entity.CaseErpStoreReceiptDetail;
import com.xjrsoft.module.erpModel.caseErpStore.mapper.CaseErpStoreReceiptMapper;
import com.xjrsoft.module.erpModel.caseErpStore.service.ICaseErpStoreReceiptDetailService;
import com.xjrsoft.module.erpModel.caseErpStore.service.ICaseErpStoreReceiptService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xjrsoft.module.organization.entity.User;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * <p>
 * 出入库单据信息表【case_erp_store_receipt】 服务实现类
 * </p>
 *
 * @author hnyyzy
 * @since 2023-07-20
 */
@Service
@AllArgsConstructor
public class CaseErpStoreReceiptServiceImpl extends ServiceImpl<CaseErpStoreReceiptMapper, CaseErpStoreReceipt> implements ICaseErpStoreReceiptService {

    private final ICaseErpMaterialService caseErpMaterialService;

    private final ICaseErpStoreReceiptDetailService caseErpStoreReceiptDetailService;

    private final RedisUtil redisUtil;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean delete(Long id) {
        this.removeById(id);
        List<CaseErpStoreReceiptDetail> list = caseErpStoreReceiptDetailService.list(Wrappers.<CaseErpStoreReceiptDetail>query().lambda().eq(CaseErpStoreReceiptDetail::getStoreReceiptId, id));
        this.deleteDetail(list);
        return true;
    }

    /**
     * 删除出入库表详情数据以及把库存还原
     * @param list 出入库表详情表list集合
     */
    public void deleteDetail(List<CaseErpStoreReceiptDetail> list){
        List<CaseErpMaterial> caseErpMaterialList = caseErpMaterialService.list();
        List<CaseErpMaterial> updateCaseErpMaterialList = new ArrayList<>();
        //删除之前需要先把入库或出库的库存给还原回来
        for (CaseErpStoreReceiptDetail caseErpStoreReceiptDetail : list) {
            if (StrUtil.isNotBlank(caseErpStoreReceiptDetail.getCode())){
                CaseErpMaterial caseErpMaterial = caseErpMaterialList.stream().filter(x -> x.getCode().equals(caseErpStoreReceiptDetail.getCode())).findFirst().orElse(new CaseErpMaterial());
                if (ObjectUtil.isNotEmpty(caseErpMaterial.getInventory())){
                    if (caseErpStoreReceiptDetail.getOperateType() == 2){//销售订单
                        caseErpMaterial.setInventory(caseErpMaterial.getInventory().add(caseErpStoreReceiptDetail.getCount()));
                        updateCaseErpMaterialList.add(caseErpMaterial);
                    }else if (caseErpStoreReceiptDetail.getOperateType() == 3){//采购订单
                        caseErpMaterial.setInventory(caseErpMaterial.getInventory().subtract(caseErpStoreReceiptDetail.getCount()));
                        updateCaseErpMaterialList.add(caseErpMaterial);
                    }
                }
            }
        }
        caseErpMaterialService.updateBatchById(updateCaseErpMaterialList);
        caseErpStoreReceiptDetailService.removeBatchByIds(list);
    }

    /**
     * 添加出入库表详情数据以及把库存还原
     * @param caseErpStoreReceiptDetailList
     * @param caseErpStoreReceipt
     */
    public void addDetail(List<CaseErpStoreReceiptDetail> caseErpStoreReceiptDetailList,CaseErpStoreReceipt caseErpStoreReceipt){
        List<CaseErpMaterial> caseErpMaterialList = caseErpMaterialService.list();
        List<CaseErpMaterial> updateCaseErpMaterialList = new ArrayList<>();
        for (CaseErpStoreReceiptDetail caseErpStoreReceiptDetail : caseErpStoreReceiptDetailList) {
            caseErpStoreReceiptDetail.setStoreReceiptId(caseErpStoreReceipt.getId());
            if (caseErpStoreReceipt.getStoreType() == YesOrNoEnum.YES.getCode()) { // 入库则是采购订单
                caseErpStoreReceiptDetail.setOperateType(3);//设置操作类型为采购订单
                if (StrUtil.isNotBlank(caseErpStoreReceiptDetail.getCode())){
                    CaseErpMaterial caseErpMaterial = caseErpMaterialList.stream().filter(x -> x.getCode().equals(caseErpStoreReceiptDetail.getCode())).findFirst().orElse(new CaseErpMaterial());
                    if (ObjectUtil.isNotEmpty(caseErpMaterial.getInventory())){//库存数不为空，采购订单则需增加库存数量,物料表库存数量需要增加
                        caseErpStoreReceiptDetail.setLocalInventory(caseErpMaterial.getInventory().add(caseErpStoreReceiptDetail.getCount()));//设置当前库存数量
                        caseErpMaterial.setInventory(caseErpStoreReceiptDetail.getLocalInventory());
                        updateCaseErpMaterialList.add(caseErpMaterial);
                    }
                }
            }else {//出库则是销售订单
                caseErpStoreReceiptDetail.setOperateType(2);//设置操作类型为销售订单
                if (StrUtil.isNotBlank(caseErpStoreReceiptDetail.getCode())){
                    CaseErpMaterial caseErpMaterial = caseErpMaterialList.stream().filter(x -> x.getCode().equals(caseErpStoreReceiptDetail.getCode())).findFirst().orElse(new CaseErpMaterial());
                    if (ObjectUtil.isNotEmpty(caseErpMaterial.getInventory())){//库存数不为空，销售则需减少库存数量,物料表库存数量需要减少
                        caseErpStoreReceiptDetail.setLocalInventory(caseErpMaterial.getInventory().subtract(caseErpStoreReceiptDetail.getCount()));//设置当前库存数量
                        caseErpMaterial.setInventory(caseErpStoreReceiptDetail.getLocalInventory());
                        updateCaseErpMaterialList.add(caseErpMaterial);
                    }
                }
            }
        }
        caseErpStoreReceiptDetailService.saveBatch(caseErpStoreReceiptDetailList);
        caseErpMaterialService.updateBatchById(updateCaseErpMaterialList);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean add(AddCaseErpStoreReceiptDto dto) {
        CaseErpStoreReceipt caseErpStoreReceipt = BeanUtil.toBean(dto, CaseErpStoreReceipt.class);
        if (StrUtil.isNotBlank(caseErpStoreReceipt.getPersonIds())) {
            List<User> allUser = redisUtil.get(GlobalConstant.USER_CACHE_KEY, new TypeReference<List<User>>() {
            });
            String allUserIdStr = StrUtil.join(StringPool.COMMA, caseErpStoreReceipt.getPersonIds());
            List<Long> ids = Arrays.stream(allUserIdStr.split(StringPool.COMMA)).map(Convert::toLong).collect(Collectors.toList());
            List<String> names = allUser.stream().filter(x -> ids.contains(x.getId())).map(User::getName).collect(Collectors.toList());
            caseErpStoreReceipt.setPersonNames(StrUtil.join(StringPool.COMMA, names));
        }
        this.save(caseErpStoreReceipt);
        List<CaseErpStoreReceiptDetail> caseErpStoreReceiptDetailList = BeanUtil.copyToList(dto.getAddCaseErpStoreReceiptDetailDtoList(), CaseErpStoreReceiptDetail.class);
        if (CollectionUtil.isNotEmpty(caseErpStoreReceiptDetailList)) {
            this.addDetail(caseErpStoreReceiptDetailList,caseErpStoreReceipt);
        }
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean edit(UpdateCaseErpStoreReceiptDto dto) {
        CaseErpStoreReceipt caseErpStoreReceipt = BeanUtil.toBean(dto, CaseErpStoreReceipt.class);
        if (StrUtil.isNotBlank(caseErpStoreReceipt.getPersonIds())) {
            List<User> allUser = redisUtil.get(GlobalConstant.USER_CACHE_KEY, new TypeReference<List<User>>() {
            });
            String allUserIdStr = StrUtil.join(StringPool.COMMA, caseErpStoreReceipt.getPersonIds());
            List<Long> ids = Arrays.stream(allUserIdStr.split(StringPool.COMMA)).map(Convert::toLong).collect(Collectors.toList());
            List<String> names = allUser.stream().filter(x -> ids.contains(x.getId())).map(User::getName).collect(Collectors.toList());
            caseErpStoreReceipt.setPersonNames(StrUtil.join(StringPool.COMMA, names));
        }
        this.updateById(caseErpStoreReceipt);
        // 查出所有子级的id
        List<CaseErpStoreReceiptDetail> caseErpStoreReceiptDetailList = caseErpStoreReceiptDetailService.list(Wrappers.lambdaQuery(CaseErpStoreReceiptDetail.class).eq(CaseErpStoreReceiptDetail::getStoreReceiptId, caseErpStoreReceipt.getId()));
        List<Long> collect = caseErpStoreReceiptDetailList.stream().map(CaseErpStoreReceiptDetail::getId).collect(Collectors.toList());
        //原有子表单 没有被删除的主键
        List<Long> oldIds = dto.getAddCaseErpStoreReceiptDetailDtoList().stream().map(UpdateCaseErpStoreReceiptDetailDto::getId).filter(Objects::nonNull).collect(Collectors.toList());
        //找到需要删除的id
        List<Long> removeIds = collect.stream().filter(item -> !oldIds.contains(item)).collect(Collectors.toList());

        List<CaseErpStoreReceiptDetail> updateCaseErpStoreReceiptDetails = new ArrayList<>();
        List<CaseErpStoreReceiptDetail> addCaseErpStoreReceiptDetails = new ArrayList<>();
        List<CaseErpMaterial> caseErpMaterialList = caseErpMaterialService.list();
        List<CaseErpMaterial> updateCaseErpMaterialList = new ArrayList<>();
        for (UpdateCaseErpStoreReceiptDetailDto updateCaseErpStoreReceiptDetailDto : dto.getAddCaseErpStoreReceiptDetailDtoList()) {
            //如果不等于空则修改
            if (updateCaseErpStoreReceiptDetailDto.getId() != null) {
                CaseErpStoreReceiptDetail caseErpStoreReceiptDetail = BeanUtil.toBean(updateCaseErpStoreReceiptDetailDto, CaseErpStoreReceiptDetail.class);
                //判断数量是否有所改变
                CaseErpStoreReceiptDetail oldCaseErpStoreReceiptDetail = caseErpStoreReceiptDetailList.stream().filter(x -> x.getId().equals(updateCaseErpStoreReceiptDetailDto.getId())).findFirst().orElse(new CaseErpStoreReceiptDetail());
                if (ObjectUtil.isNotEmpty(oldCaseErpStoreReceiptDetail.getCount()) && oldCaseErpStoreReceiptDetail.getCount().compareTo(caseErpStoreReceiptDetail.getCount()) != 0){ //不相等
                    //需要修改物料的库存值
                    CaseErpMaterial caseErpMaterial = caseErpMaterialList.stream().filter(x -> x.getCode().equals(caseErpStoreReceiptDetail.getCode())).findFirst().orElse(new CaseErpMaterial());
                    if(ObjectUtil.isNotEmpty(oldCaseErpStoreReceiptDetail.getOperateType()) && oldCaseErpStoreReceiptDetail.getOperateType() == 2){ //关联的销售订单数据
                        caseErpMaterial.setInventory(caseErpMaterial.getInventory().add(oldCaseErpStoreReceiptDetail.getCount().subtract(caseErpStoreReceiptDetail.getCount())));
                        updateCaseErpMaterialList.add(caseErpMaterial);
                    }else { //关联的采购订单数据
                        caseErpMaterial.setInventory(caseErpMaterial.getInventory().subtract(oldCaseErpStoreReceiptDetail.getCount()).add(caseErpStoreReceiptDetail.getCount()));
                        updateCaseErpMaterialList.add(caseErpMaterial);
                    }
                }
                updateCaseErpStoreReceiptDetails.add(caseErpStoreReceiptDetail);
            }
            //如果等于空 则新增
            else {
                //已经不存在的id 删除
                CaseErpStoreReceiptDetail caseErpStoreReceiptDetail = BeanUtil.toBean(updateCaseErpStoreReceiptDetailDto, CaseErpStoreReceiptDetail.class);
                caseErpStoreReceiptDetail.setStoreReceiptId(caseErpStoreReceipt.getId());
                addCaseErpStoreReceiptDetails.add(caseErpStoreReceiptDetail);
            }
        }
        caseErpStoreReceiptDetailService.updateBatchById(updateCaseErpStoreReceiptDetails);
        //添加详情表数据
        this.addDetail(addCaseErpStoreReceiptDetails,caseErpStoreReceipt);
        caseErpMaterialService.updateBatchById(updateCaseErpMaterialList);
        //已经不存在的id 删除
        if(removeIds.size() > 0){
            //先还原库存
            List<CaseErpStoreReceiptDetail> removeDetailList = caseErpStoreReceiptDetailList.stream().filter(x -> removeIds.contains(x.getId())).collect(Collectors.toList());
            this.deleteDetail(removeDetailList);
        }
        return true;
    }


}
